/******************************************************************************/
                             /* FILE: BUTTON.C */
/******************************************************************************/
/* 
 * MODULE NAME: BUTTON
 * AUTHOR     : Jacques-Olivier KLEIN
 * EMAIL      : http://www.ief.u-psud.fr/~jok
 * INSTITUTION: IUT de CACHAN - BP140 - 94234 CACHAN
 * DATE       : 2011-05-26 (18:18)
 * 
 * CPU        : MOTOROLA MC9S12DP256 
 * BOARD      : CACHAN Star12 Developpement kit
 * OS         : None
 * 
 * 
 * DESCRIPTION: Fonction de gestion des bouttons. 
 * NOTE       : L'utilisation et la copie de ce fichier dans un etablissemen
 *              t d'enseignement ou de recherche public sont autorisées.
 */
 
 /*****  !! EN COURS : NON COMPILE - N O N   T E S T E  !!  ******* */
 
#include <limits.h>
#include "BUTTON.H"
#include "X12_REVEIL_lib.h"

static  void bp_fifo_put(unsigned char); 


 /*
  * Cette fonction est appellee periodiquement typiquement toutes les 10ms
  * Elle scrute les boutons et
  * envoie des evenements dans une fifo. Les evenements sont definis  
  * par les besoins de l'application : bouton X enfonce, bouton relache depuis 10s. 
  * Les rebonds et le maitien appuye sont geres par une machine d'etat (9 états). 
  * Un etat de depart + 4 etats pour la detection des 4 boutons + 4 etats
  * pour la detection des appuis long de chaque bouton. 
  * Un compteur permet de detecter les appui longs et de generer une auto-repetition.  
  */
void button_fsm (void){
    typedef enum {bpstate_idle, bpstate_up1, bpstate_up2,  
      bpstate_middle1, bpstate_middle2, bpstate_left1, bpstate_left2, 
      bpstate_right1, bpstate_right2} T_BUTTON_STATE;
    static T_BUTTON_STATE state = bpstate_idle;
    static unsigned int counter = 0; 
    unsigned char button;

    button = (~(BP3<<3|BP2<<2|BP1<<1|BP0))&0x0F;

    if (counter != UINT_MAX){counter++;}
    
 	switch (state){
    	case bpstate_idle:
   		    if(counter == FSM_FREQUENCY_HZ*10 ){
    				bp_fifo_put(BUTTON_LONG_BLANK_MASK);
    				counter = 0; 
    		}
    		switch(button) {
     			case BUTTON_UP_MASK:
    			state = bpstate_up1;
    			counter = 0;
    			break;
    			
    			case BUTTON_LEFT_MASK:
    			state = bpstate_left1;
    			counter = 0;
    			break;
    			
    			case BUTTON_MIDDLE_MASK:
    			state = bpstate_middle1;
    			counter = 0;
    			break;
    			
    			case BUTTON_RIGHT_MASK:
    			state = bpstate_right1;
    			counter = 0;
    			break;
    		}
    	break; 
    	
    	case bpstate_up1:
    		if (button!=BUTTON_UP_MASK){
     			state = bpstate_idle ;
    			counter = 0;   		
    		}else if(counter == FSM_FREQUENCY_HZ/10 ){
     			state = bpstate_up2 ;
    			counter = 0;   	
    			bp_fifo_put(BUTTON_UP_MASK);
    		}
    	break; 
    	case bpstate_up2:
    		if (button!=BUTTON_UP_MASK){
     			state = bpstate_idle ;
    			counter = 0;   		
    		}else if(counter >= FSM_FREQUENCY_HZ*5 &&  (counter% (FSM_FREQUENCY_HZ/5))==0){
    			bp_fifo_put(BUTTON_UP_MASK);
    		}else if(counter >= FSM_FREQUENCY_HZ*1 &&  (counter% (FSM_FREQUENCY_HZ))==0){
    			bp_fifo_put(BUTTON_UP_MASK);
    		}
    	break; 
    	
    	case bpstate_middle1:
    		if (button!=BUTTON_MIDDLE_MASK){
     			state = bpstate_idle ;
    			counter = 0;   		
    		}else if(counter == FSM_FREQUENCY_HZ/10 ){
     			state = bpstate_middle2 ;
    			counter = 0;   	
    			bp_fifo_put(BUTTON_MIDDLE_MASK);
    		}
    	break; 
    	case bpstate_middle2:
    		if (button!=BUTTON_MIDDLE_MASK){
     			state = bpstate_idle ;
    			counter = 0;   		
    		}else if(counter >= FSM_FREQUENCY_HZ*5 &&  (counter% (FSM_FREQUENCY_HZ/5))==0){
    			bp_fifo_put(BUTTON_MIDDLE_MASK);
    		}else if(counter >= FSM_FREQUENCY_HZ*1 &&  (counter% (FSM_FREQUENCY_HZ))==0){
    			bp_fifo_put(BUTTON_MIDDLE_MASK);
    		}
    	break; 
    	
    	case bpstate_left1:
    		if (button!=BUTTON_LEFT_MASK){
     			state = bpstate_idle ;
    			counter = 0;   		
    		}else if(counter == FSM_FREQUENCY_HZ/10 ){
     			state = bpstate_left2 ;
    			counter = 0;   	
    			bp_fifo_put(BUTTON_LEFT_MASK);
    		}
    	break; 
    	case bpstate_left2:
    		if (button!=BUTTON_LEFT_MASK){
     			state = bpstate_idle ;
    			counter = 0;   		
//    		}else if(counter >= FSM_FREQUENCY_HZ*5 &&  (counter% (FSM_FREQUENCY_HZ/5))==0){
//    			bp_fifo_put(BUTTON_LEFT_MASK);
    		}else if(counter >= FSM_FREQUENCY_HZ*1 &&  (counter% (FSM_FREQUENCY_HZ))==0){
    			bp_fifo_put(BUTTON_LEFT_MASK);
    		}
    	break; 
    	
    	case bpstate_right1:
    		if (button!=BUTTON_RIGHT_MASK){
     			state = bpstate_idle ;
    			counter = 0;   		
    		}else if(counter == FSM_FREQUENCY_HZ/10 ){
     			state = bpstate_right2 ;
    			counter = 0;   	
    			bp_fifo_put(BUTTON_RIGHT_MASK);
    		}
    	break; 
    	case bpstate_right2:
    		if (button!=BUTTON_RIGHT_MASK){
     			state = bpstate_idle ;
    			counter = 0;   		
//    		}else if(counter >= FSM_FREQUENCY_HZ*5 &&  (counter% (FSM_FREQUENCY_HZ/5))==0){
//    			bp_fifo_put(BUTTON_RIGHT_MASK);
    		}else if(counter >= FSM_FREQUENCY_HZ*1 &&  (counter% (FSM_FREQUENCY_HZ))==0){
    			bp_fifo_put(BUTTON_RIGHT_MASK);
    		}
    	break; 
    	
    }//end case
 }
 
// FIFO de taille 1 !
static unsigned char bp_event; 
 
static void bp_fifo_put(unsigned char event){
  	bp_event =  event; 
}

unsigned char bp_fifo_get(void){
	unsigned char event; 
	event = bp_event; 
	bp_event = BUTTON_NO_EVENT; 
	return event;
 }
 
 

 
